/*
 * Created by Jaren at 2022/2/21 15:53
 */
import 'dart:async';
import 'dart:io';

import 'package:inmotion_protocol/base/base_message.dart';
import 'package:inmotion_protocol/base/file/file_manager.dart';
import 'package:inmotion_protocol/base/protocol.dart';
import 'package:inmotion_protocol/common/file.dart' as protocol_file;
import 'package:inmotion_protocol/common/media_file_upload_manager.dart';
import 'package:inmotion_protocol/lorin/file/browse_file_method.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file_manager.dart';

class LorinSoundFileUploadManager extends SoundFileUploadManager {
  LorinSoundFileUploadManager(Protocol<IMessage> protocol) : super(protocol);

  @override
  Future<bool> clearCacheFiles() {
    return protocol.getFileList(filter: BrowseFileMethodBuilder().fileOnly().depthCurrentDir().fileType('tmp').withPath('0:/audio').build()).then((rsp) {
      if (!rsp.isSuccess()) return false;

      List<protocol_file.File> tmpFiles = [];
      List<protocol_file.File> files = rsp.files;
      for (protocol_file.File file in files) {
        file as LorinFile;
        if (file.isDirectory() || file.name == '') continue;
        if (file.name.toUpperCase().endsWith("TMP")) {
          tmpFiles.add(file);
        }
      }
      if (tmpFiles.isEmpty) return false;

      for (protocol_file.File file in tmpFiles) {
        deleteFile((file as LorinFile).getAbsolutePath());
      }
      return true;
    });
  }

  void deleteFile(String filePath) async {
    await protocol.deleteFile(filePath);
  }

  @override
  MediaUploadConfig createSoundItemConfig(File localFile, int itemIndex) {
    return LorinSoundFileConfig.createByAudioItem(fileOperationTargetDevice(), localFile, itemIndex);
  }

  @override
  MediaUploadConfig createSoundPackConfig(File localFile, int pkgId) {
    return LorinSoundFileConfig.createBySoundPack(fileOperationTargetDevice(), localFile, pkgId);
  }

  @override
  Future renameFileIfNeed(int id, StreamController<UploadEvent> streamController) {
    MediaUploadConfig config = getConfig!;
    String filePath = (config as LorinFileManagerConfig).remoteFilename;
    String newFilePath = filePath.substring(0, filePath.length - 3) + "rmf";
    return protocol.deleteFile(newFilePath).then((rsp) {
      if (rsp.isSuccess()) {
        return protocol.renameFile(filePath, newFilePath).then((rsp) {
          if (rsp.isSuccess()) return true;
          // TODO throw step error
          throw FileRenameFailedException();
        }).catchError((e) {
          throw e;
        });
      }
      // TODO throw step error
      throw FileRenameFailedException();
    }).catchError((e) {
      throw e;
    });
  }

  @override
  Future<bool> checkStorageCapacityImpl(int size) {
    // V11通过剩余容量判断
    if (protocol.productProperty.model.isV11Series()) return super.checkStorageCapacityImpl(size);
    // 其余通过文件数量判断
    return getSoundFileCount().then((count) => count < 5).onError((Exception error, stackTrace) => throw error);
  }

  Future<int> getSoundFileCount([int initCount = 0]) {
    getFileCountImpl(int initCount) {
      return protocol.getFileList(filter: BrowseFileMethodBuilder().fileOnly().depthCurrentDir().fileType('rmf').withPath('0:/audio').build()).then((rsp) {
        if (!rsp.isSuccess()) throw Error();

        for (protocol_file.File file in rsp.files) {
          file as LorinFile;
          if (file.isDirectory() || file.name == '') continue;
          if (!file.name.toUpperCase().endsWith("RMF")) {
            // 非有效音效文件
            continue;
          }
          initCount++;
        }
        return {'count': initCount, 'remain': rsp.remain};
      }).onError((Exception error, stackTrace) {
        throw error;
      });
    }

    return getFileCountImpl(initCount).then((map) {
      if (map['remain'] == 0) return map['count']!;
      return getSoundFileCount(initCount);
    });
  }
}

class LorinSoundFileConfig extends LorinFileManagerConfig implements MediaUploadConfig {
  @override
  int id;

  LorinSoundFileConfig(int target, int openType, String remoteFilename, File localFile, this.id) : super(target, openType, remoteFilename, localFile);

  static LorinSoundFileConfig createBySoundPack(int target, File localFile, int pkgId) {
    return LorinSoundFileConfig(target, IFileManager.openFileTypeReadWrite2, "0:/audio/$pkgId.tmp", localFile, pkgId);
  }

  static LorinSoundFileConfig createByAudioItem(int target, File localFile, int soundIndex) {
    return LorinSoundFileConfig(target, IFileManager.openFileTypeReadWrite2, "0:/audio/diy/${soundIndex + 1}.tmp", localFile, soundIndex);
  }
}
